use std::sync::Arc;

use anyhow::Context;
use async_trait::async_trait;
use russh::{*, client::Msg};
use russh_keys::*;

struct Client {}

#[async_trait]
impl client::Handler for Client {
    type Error = russh::Error;

    async fn check_server_key(
        self,
        server_public_key: &key::PublicKey,
    ) -> Result<(Self, bool), Self::Error> {
        println!("check_server_key: {:?}", server_public_key);
        Ok((self, true))
    }
}

pub async fn start() {
    env_logger::init();
    let config = russh::client::Config::default();
    let config = Arc::new(config);
    let sh = Client {};

    let mut session = russh::client::connect(config, ("192.168.1.157", 22), sh)
        .await
        .unwrap();
    let auth_res = session
        .authenticate_password("isms", "itc123")
        .await
        .unwrap();
    println!("=== auth: {}", auth_res);
    let mut channel = session.channel_open_session().await.unwrap();
    let mode1 = (Pty::ICRNL, 1u32);
    let mode2 = (Pty::ECHO, 0u32);
    let terminal_modes = [mode2, mode1];
    let _ = channel.request_pty(true, "xterm", 100, 50, 100, 100, &terminal_modes);
    let _ = channel.request_shell(true);

    println!("=== after open channel");
    let data = b"GET /les_affames.mkv HTTP/1.1\nUser-Agent: curl/7.68.0\nAccept: */*\nConnection: close\n\n";
    // let data1 = CryptoVec::from(format!("Got data: {}\r\n", String::from_utf8_lossy(data)));
    let data1 = CryptoVec::from(format!("touch test111111111.txt\r"));
    println!("data={:?}", data);
    // let msg = ChannelMsg::Data { data: data1 };
    session.data(channel.id(), data1).await.unwrap();
    
    
    let data = b"GET /les_affames.mkv HTTP/1.1\nUser-Agent: curl/7.68.0\nAccept: */*\nConnection: close\n\n";
    // let msg = ChannelMsg::Data { data: data1 };
    // session.data(channel.id(), msg);
    
    
    // channel.data(&data[..]).await.unwrap();
    // channel.data(data).await.unwrap();
    // println!("create file ...");
    // let mut f = std::fs::File::create("les_affames.mkv").unwrap();
    println!("while ...");
    
    while let Some(msg) = channel.wait().await {
        
        println!("while loop");
        match msg {
            russh::ChannelMsg::Data { ref data } => {
                println!("data={:?}", data);
            }
            russh::ChannelMsg::Eof => {
                println!("eof");
                break;
            }
            _ => {}
        }
    }
    session
        .disconnect(Disconnect::ByApplication, "", "English")
        .await
        .unwrap();
    let res = session.await.context("session await");
    println!("{:#?}", res);
}
